package com.cardone.common.util;

import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.core.io.Resource;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * web工具类
 *
 * @author yaohaitao
 */
@Slf4j
public class WebUtils {
    private WebUtils() {
    }

    /**
     * 获取request
     *
     * @return request
     */
    public static HttpServletRequest getRequest() {
        final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        if (requestAttributes == null) {
            return null;
        }

        final HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

        return request;
    }

    /**
     * 获取bean关于json
     *
     * @param mappedClass 映射类型
     * @return bean @
     */
    public static <T> T getBeanForJson(final Class<T> mappedClass) {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return null;
        }

        return WebUtils.getBeanForJson(mappedClass, request);
    }

    /**
     * 获取bean关于json
     *
     * @param mappedClass 映射类型
     * @param request
     * @return bean @
     */
    public static <T> T getBeanForJson(final Class<T> mappedClass, final HttpServletRequest request) {
        final String jsonString = WebUtils.getJsonString(request);

        return MapperUtils.fromJson(mappedClass, jsonString);
    }

    public static boolean isReadJson(final ServletRequest request) {
        return org.apache.commons.lang3.StringUtils.startsWith(request.getContentType(), com.google.common.net.MediaType.ANY_APPLICATION_TYPE.type());
    }

    /**
     * 获取json字符串
     *
     * @param request
     * @return json字符串
     */
    public static String getJsonString(final ServletRequest request) {
        boolean readJson = isReadJson(request);

        if (readJson) {
            String jsonString = null;

            try (java.io.InputStream is = request.getInputStream()) {
                jsonString = IOUtils.toString(is, request.getCharacterEncoding());
            } catch (final IOException e) {
                WebUtils.log.error(e.getMessage(), e);
            }

            if (StringUtils.isNotBlank(jsonString)) {
                return jsonString;
            }
        }

        final Map<String, Object> parameterMap = org.springframework.web.util.WebUtils.getParametersStartingWith(request, null);

        if (MapUtils.isEmpty(parameterMap)) {
            return null;
        }

        return MapperUtils.toJson(parameterMap);
    }

    @Setter
    @Getter
    public static List<String> searchKeys = Lists.newArrayList("client_id", "token");

    public static Map<String, Object> getParameterMap(final ServletRequest request) {
        final Map<String, Object> parameterMap = org.springframework.web.util.WebUtils.getParametersStartingWith(request, null);

        if (isReadJson(request)) {
            try (java.io.InputStream is = request.getInputStream()) {
                String jsonString = IOUtils.toString(is, request.getCharacterEncoding());

                if (StringUtils.isNotBlank(jsonString)) {
                    Map<String, Object> jsonMap = MapperUtils.fromJsonForMap(jsonString);

                    if (MapUtils.isNotEmpty(jsonMap)) {
                        parameterMap.putAll(jsonMap);
                    }
                }
            } catch (final IOException e) {
                WebUtils.log.error(e.getMessage(), e);
            }
        }

        if (!org.springframework.util.CollectionUtils.isEmpty(searchKeys) && request instanceof HttpServletRequest) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;

            for (String headerKey : searchKeys) {
                if (parameterMap.containsKey(headerKey)) {
                    continue;
                }

                parameterMap.put(headerKey, httpServletRequest.getHeader(headerKey));
            }
        }

        return parameterMap;
    }

    /**
     * 获取bean关于json
     *
     * @param mappedClass 映射类型
     * @param paramName   参数名称
     * @return bean @
     */
    public static <T> T getBeanForJson(final Class<T> mappedClass, final String paramName) {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return null;
        }

        return WebUtils.getBeanForJson(mappedClass, paramName, request);
    }

    @Setter
    private static String defaultServletPath = "/index.html";

    public static String getServletPath(HttpServletRequest request) {
        String servletPath = request.getServletPath();

        return StringUtils.defaultIfBlank(servletPath, defaultServletPath);
    }

    public static String getServletPath(javax.servlet.ServletRequest request) {
        if (request instanceof HttpServletRequest) {
            String servletPath = ((HttpServletRequest) request).getServletPath();

            return StringUtils.defaultIfBlank(servletPath, defaultServletPath);
        }

        return StringUtils.EMPTY;
    }


    public static String getServletPath() {
        final HttpServletRequest request = getRequest();

        return getServletPath(request);
    }

    public static String getRequestUri(HttpServletRequest request) {
        String requestUri = request.getRequestURI();

        if (StringUtils.isNotBlank(requestUri)) {
            SecurityUtils.getSubject().getSession().setAttribute("requestUri", requestUri);

            return requestUri;
        }

        return (String) SecurityUtils.getSubject().getSession().getAttribute("requestUri");
    }

    public static String getRequestUri() {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return (String) SecurityUtils.getSubject().getSession().getAttribute("requestUri");
        }

        return getRequestUri(request);
    }


    public static String getContextPath(HttpServletRequest request) {
        String contextPath = request.getContextPath();

        if (StringUtils.isNotBlank(contextPath)) {
            SecurityUtils.getSubject().getSession().setAttribute("contextPath", contextPath);

            return contextPath;
        }

        return (String) SecurityUtils.getSubject().getSession().getAttribute("contextPath");
    }

    public static String getContextPath() {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return (String) SecurityUtils.getSubject().getSession().getAttribute("contextPath");
        }

        return getContextPath(request);
    }


    public static String getServerName(HttpServletRequest request) {
        String serverName = request.getServerName();

        if (StringUtils.isNotBlank(serverName)) {
            SecurityUtils.getSubject().getSession().setAttribute("serverName", serverName);

            return serverName;
        }

        return (String) SecurityUtils.getSubject().getSession().getAttribute("serverName");
    }

    public static String getServerName() {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return (String) SecurityUtils.getSubject().getSession().getAttribute("serverName");
        }

        return getServerName(request);
    }

    public static String getParameterValue(HttpServletRequest request, String parameterName) {
        return getParameterValue(request, WebUtils.getParameterMap(request), parameterName);
    }

    public static String getParameterValue(HttpServletRequest request, Map<String, Object> parameterMap, String parameterName) {
        String parameterValue;

        if (parameterMap == null) {
            parameterValue = request.getParameter(parameterName);
        } else {
            parameterValue = MapUtils.getString(parameterMap, parameterName);
        }

        if (StringUtils.isNotBlank(parameterValue)) {
            return parameterValue;
        }

        return request.getHeader(parameterName);
    }


    public static String getSessionId() {
        return SecurityUtils.getSubject().getSession().getId().toString();
    }

    /**
     * 获取bean关于json
     *
     * @param mappedClass 映射类型
     * @param paramName   参数名称
     * @param request
     * @return bean @
     */
    public static <T> T getBeanForJson(final Class<T> mappedClass, final String paramName, final HttpServletRequest request) {
        final String jsonString = WebUtils.getJsonString(request);

        return MapperUtils.fromJsonByParamName(mappedClass, paramName, jsonString);
    }

    /**
     * 获取json字符串
     *
     * @return json字符串
     */
    public static String getJsonString() {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return MapperUtils.toJson(Maps.newHashMap());
        }

        return WebUtils.getJsonString(request);
    }

    /**
     * 数据位置
     */
    @Setter
    @Getter
    private static Resource rootLocation;

    /**
     * 获取文件
     *
     * @param filename 文件名
     * @return
     * @throws IOException
     */
    public static File getFile(String filename) throws IOException {
        String newFilename = rootLocation.getFile().getAbsolutePath() + filename;

        return new File(newFilename);
    }

    /**
     * 读取文件字符串
     *
     * @param filename 文件名
     * @return
     * @throws IOException
     */
    public static String readFileToString(String filename) throws IOException {
        return FileUtils.readFileToString(getFile(filename), Charsets.UTF_8);
    }

    /**
     * 读取文件字符串
     *
     * @param filename 文件名
     * @param encoding
     * @return
     * @throws IOException
     */
    public static String readFileToString(String filename, Charset encoding) throws IOException {
        return FileUtils.readFileToString(getFile(filename), encoding);
    }

    /**
     * 读取文件字符串
     *
     * @param filename 文件名
     * @param encoding
     * @return
     * @throws IOException
     */
    public static String readFileToString(String filename, String encoding) throws IOException {
        return FileUtils.readFileToString(getFile(filename), encoding);
    }

    /**
     * 获取键值对
     *
     * @return 键值对 @
     */
    public static Map<String, Object> getMapForJson() {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return Maps.newHashMap();
        }

        return WebUtils.getMapForJson(request);
    }

    /**
     * 获取键值对
     *
     * @param request
     * @return 键值对 @
     */
    public static Map<String, Object> getMapForJson(final HttpServletRequest request) {
        final String jsonString = WebUtils.getJsonString(request);

        return MapperUtils.fromJsonForMap(jsonString);
    }

    /**
     * 获取对象
     *
     * @param paramName 参数名称
     * @return 对象 @
     */
    public static Object getObjectForJson(final String paramName) {
        final HttpServletRequest request = getRequest();

        if (request == null) {
            return null;
        }

        return WebUtils.getObjectForJson(paramName, request);
    }

    /**
     * 获取对象
     *
     * @param paramName 参数名称
     * @param request
     * @return 对象 @
     */
    public static Object getObjectForJson(final String paramName, final HttpServletRequest request) {
        final String jsonString = WebUtils.getJsonString(request);

        return MapperUtils.fromJsonByParamNameForObject(paramName, jsonString);
    }
}
